package tree.nodeType.numeric.functions;

import java.util.ArrayList;
import java.util.Random;

import model.Data;
import model.Stock;
import pools.PoolsManager;
import tree.Node;
import tree.TreeNodesManager;
import tree.nodeType.Numeric;
import tree.nodeType.numeric.NumericFunction;

/**
 * return the minimum Stock in the last days.
 *
 */
public class Minimum extends NumericFunction{
	
	//private int days;
	//private Stock stock;
	
	public Minimum(Node parent,int depth, int maxDepth, TreeNodesManager treeNodesManager) {
		super(1,parent,treeNodesManager,depth);
		initSons(depth, maxDepth,treeNodesManager);
	}
	public Minimum() {}
	public double execute() {
		Stock stock= Data.get().getCurrentStock();
		double min = Double.MAX_VALUE;
		if (!sons.isEmpty()){
			days=Math.abs((int) Math.round(((Numeric)sons.get(0)).execute()));
		}
		int startDay=stock.getClosePrice().size()-1;
		if (Data.get().getPhase()==Data.Phase.Train){
			startDay= stock.getClosePrice().size()-1 - Data.get().getDays();
		}
		int lastDay = (startDay - days);
		if (startDay > stock.getClosePrice().size()-1){
			startDay=stock.getClosePrice().size()-1;			
		}
		if (lastDay < 0){
			lastDay=0;		
		}
		if (startDay - lastDay > 400){
			lastDay = startDay - 400;
			if (lastDay<0){
				lastDay=0;
			}
		}
		for (int i=startDay; i>lastDay; i--){
			if (stock.getClosePrice().get(i)<min){
				min = stock.getClosePrice().get(i);
			}
		}
		return min;
	}


	@Override
	public void initSons(int depth, int maximumDepth, TreeNodesManager treeNodesManager) {
		if (depth+1<=maximumDepth && (random.nextDouble()<0.5 || depth<2)){
			sons.add(PoolsManager.get().getRandomNumericFuncNode(depth+1, maximumDepth, this,treeNodesManager));
		}

	}
	
	@Override
	public String toString() {	
		return "Minimum function: days: "+days;
	}
	@Override
	protected Node clone(TreeNodesManager treeNodesManager,Node parent) {
		Node cloned= new Minimum(this,treeNodesManager,parent);		
		return cloned;
	}
	
	@Override
	protected Node clone(Node parent) {
		Node cloned= new Minimum(this,parent);		
		return cloned;
	}
	
	public Minimum(Minimum min,Node parent){
		this.depth=min.depth;
		this.days=min.days;
		this.parent=parent;
		this.sonsNeeded=min.sonsNeeded;
		this.random= new Random();
		this.sons= new ArrayList<Node>();
		for (Node son : min.sons){
			this.sons.add(son.cloneSubTree(this));
		}
	}
	public Minimum(Minimum min, TreeNodesManager treeNodesManager,Node parent){
		super(1,parent,treeNodesManager,min.depth,min.days);
		for (Node son : min.sons){
			this.sons.add(son.cloneSubTree(treeNodesManager,this));
		}
	}

}
